-- Analisador léxico e funções auxiliares

module Lexico
( 
	isComment,
	getWord,
	lexico
) where


import Data.Char
import Tokens
import Types


-- Verifica comentário
isComment :: String -> String
isComment str =
	    case str of
		   [] -> []
		   ('!':str) -> isComment str
		   ('\n':str) -> str
		   (a:b) -> isComment b
		   
		   
-- Extrai uma palavra da string
getWord :: String -> (String, String)
getWord str = 
		let aux s =
			case s of
				[] -> ([], [])
				(a:b) -> if Data.Char.isLetter a || Data.Char.isDigit a || a == '_' then
								let (x, y) = aux b in
								(a:x, y)
							else
								([], s)
		in
		if str /= [] then
			if Data.Char.isAlpha (head str) then
				aux str
			else
				([], str)
		else
			([], [])


-- Analisador léxico
lexico :: String -> Int -> [TLine]
lexico str line =
		case str of
			[] -> []
			('\n':s) -> lexico s	(line+1)
			('\t':s) -> lexico s	(line)
			(' ':s) -> lexico s (line)
			('!':s) -> lexico (isComment str) (line)
			('+':'.':s) -> ((line), Concat_tk):(lexico s (line))
			('+':s) -> ((line), Plus_tk):(lexico s (line))
			('-':s) -> ((line), Minus_tk):(lexico s (line))
			('*':'*':s) -> ((line), Exponential_tk):(lexico s (line))
			('*':s) -> ((line), Multiplication_tk):(lexico s (line))
			('/':'=':s) -> ((line), Diferent_tk):(lexico s (line))
			('/':s) -> ((line), Division_tk):(lexico s (line))
			('=':'=':s) -> ((line), IgualA_tk):(lexico s (line))
			('=':s) -> ((line), Equals_tk):(lexico s (line))
			('>':'=':s) -> ((line), MaiorIgualQue_tk):(lexico s (line))
			('<':'=':s) -> ((line), MenorIgualQue_tk):(lexico s (line))
			('>':s) -> ((line), MaiorQue_tk):(lexico s (line))
			('<':s) -> ((line), MenorQue_tk):(lexico s (line))
			('(':s) -> ((line), ParentesesL_tk):(lexico s (line))
			(')':s) -> ((line), ParentesesR_tk):(lexico s (line))
			('.':s) -> ((line), Point_tk):(lexico s (line)) 
			(',':s) -> ((line), Virgula_tk):(lexico s (line))
			(';':s) -> ((line), PontoVirgula_tk):(lexico s (line))
			('[':s) -> ((line), ColcheteL_tk):(lexico s (line))
			(']':s) -> ((line), ColcheteR_tk):(lexico s (line))
			('\'':s) -> ((line), Division_tk):(lexico s (line))
			('"':s) -> let [(a, b)] = reads str :: [(String, String)] in
							((line), (String_tk (length a) a)):(lexico b (line))
			(h:_) -> if Data.Char.isLetter h then
							let (a, b) = getWord str in
							((line), stringToToken a):(lexico b (line))
						else
							if Data.Char.isDigit h then
								let x = reads str :: [(Int, String)] in			-- Lê inteiro da string str
								if x == [] then
									let y = reads str :: [(Float, String)] in		-- Lê float da string str
									if y == [] then
										[((line), Error_tk)]
									else
										let [(a, b)] = y in
										if Data.Char.isLetter (head b) then
											[((line), Error_tk)]
										else
											((line), Real_tk a):(lexico b (line))
								else
									let [(a, b)] = x in
									if Data.Char.isLetter (head b) then
										[((line), Error_tk)]
									else
										((line), Integer_tk a):(lexico b (line))
							else
								[((line), Error_tk)]
